package com.tools.common.object;

import com.tools.common.container.*;

import java.util.Comparator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

/**
 * 对 Map 这些的键值对集合
 * 一些常规操作的工具类
 * 这个工具类不推荐直接开放使用
 * 建议用对象操作的工具类来调用
 * */
@Note("对 Map 这些的键值对集合一些常规操作的工具类" +
        "这个工具类不推荐直接开放使用，建议用对象操作的工具类来调用")
@SuppressWarnings("unchecked")
class PairsKit extends MapKit {

    PairsKit() {}

    /* ************************************************************************************************************
     *
     *
     *          OwnMap
     *
     * ************************************************************************************************************
     * */

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType) {
        return toOwnMap(source, keyType, valueType, MapEnum.HASH, null, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType, MapEnum impl) {
        return toOwnMap(source, keyType, valueType, impl, null, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType, MapEnum impl, Comparator<? super K> c) {
        return toOwnMap(source, keyType, valueType, impl, c, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType, ForcePair force) {
        return toOwnMap(source, keyType, valueType, MapEnum.HASH, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType, MapEnum impl, ForcePair force) {
        return toOwnMap(source, keyType, valueType, impl, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map source, C<K> keyType, C<V> valueType, MapEnum impl, Comparator<? super K> c, ForcePair force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        if(source == null || source.isEmpty()) return new OwnMap<>();
        return (OwnMap<K, V>) private_toOwnPairs(new OwnMap<>(impl, source.size(), c), source, keyType, valueType, force);
    }


    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source) {
        return toOwnMap(source, MapEnum.HASH, null, (ForcePair<K, V>) null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source, ForcePair<K, V> force) {
        return toOwnMap(source, MapEnum.HASH, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source, MapEnum impl) {
        return toOwnMap(source, impl, null, (ForcePair<K, V>) null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source, MapEnum impl, ForcePair<K, V> force) {
        return toOwnMap(source, impl, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source, MapEnum impl, Comparator<? super K> c) {
        return toOwnMap(source, impl, c, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(Map<? extends K, ? extends V> source, MapEnum impl, Comparator<? super K> c, ForcePair<K, V> force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        if(source == null || source.isEmpty()) return new OwnMap<>(impl, c);
        return (OwnMap<K, V>) private_asOwnPairs(new OwnMap<>(impl, source.size(), c), source, force);
    }


    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType) {
        return toOwnMap(source, keyType, valueType, MapEnum.HASH, null, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType, MapEnum impl) {
        return toOwnMap(source, keyType, valueType, impl, null, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType, MapEnum impl, Comparator<? super K> c) {
        return toOwnMap(source, keyType, valueType, impl, c, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType, ForcePair force) {
        return toOwnMap(source, keyType, valueType, MapEnum.HASH, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType, MapEnum impl, ForcePair force) {
        return toOwnMap(source, keyType, valueType, impl, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs source, C<K> keyType, C<V> valueType, MapEnum impl, Comparator<? super K> c, ForcePair force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        if(source != null && !source.isEmpty()) return (OwnMap<K, V>) private_toOwnPairs(new OwnMap<>(impl, source.size(), c), source, keyType, valueType, force);
        return new OwnMap<>();
    }


    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source) {
        return toOwnMap(source, MapEnum.HASH, null, (ForcePair<K, V>) null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source, ForcePair<K, V> force) {
        return toOwnMap(source, MapEnum.HASH, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source, MapEnum impl) {
        return toOwnMap(source, impl, null, (ForcePair<K, V>) null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source, MapEnum impl, ForcePair<K, V> force) {
        return toOwnMap(source, impl, null, force);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source, MapEnum impl, Comparator<? super K> c) {
        return toOwnMap(source, impl, c, null);
    }

    public static <K, V>OwnMap<K, V> toOwnMap(OwnPairs<? extends K, ? extends V> source, MapEnum impl, Comparator<? super K> c, ForcePair<K, V> force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        if(source != null && !source.isEmpty()) return (OwnMap<K, V>) private_asOwnPairs(new OwnMap<>(impl, source.size(), c), source, force);
        return new OwnMap<>(impl, c);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties) {
        return propertiesToOwnMap(properties, MapEnum.HASH, null, null);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties, ForcePair force) {
        return propertiesToOwnMap(properties, MapEnum.HASH, null, force);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties, MapEnum impl) {
        return propertiesToOwnMap(properties, impl, null, null);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties, MapEnum impl, ForcePair force) {
        return propertiesToOwnMap(properties, impl, null, force);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties, MapEnum impl, Comparator<String> c) {
        return propertiesToOwnMap(properties, impl, c, null);
    }

    public static OwnMap<String, String> propertiesToOwnMap(Properties properties, MapEnum impl, Comparator<String> c, ForcePair<String, String> force) {
        if(impl != null) {
            if(properties == null || properties.isEmpty()) return new OwnMap<>(impl, c);
            return (OwnMap<String, String>) private_propertiesAsOwnPairs(new OwnMap<>(impl, properties.size(), c), properties, force);
        }
        throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean) {
        return toOwnMap(javaBean, MapEnum.HASH, null, null);
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean, ForcePair<String, Object> force) {
        return toOwnMap(javaBean, MapEnum.HASH, null, force);
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean, MapEnum impl) {
        return toOwnMap(javaBean, impl, null, null);
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean, MapEnum impl, Comparator<String> c) {
        return toOwnMap(javaBean, impl, c, null);
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean, MapEnum impl, ForcePair<String, Object> force) {
        return toOwnMap(javaBean, impl, null, force);
    }

    public static <T>OwnMap<String, Object> toOwnMap(T javaBean, MapEnum impl, Comparator<String> c, ForcePair<String, Object> force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        OwnMap<String, Object> result = new OwnMap<>(impl, c);
        if(javaBean == null) return result;
        addAllFieldValue(result, javaBean, force);
        return result;
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties) {
        return toOwnMap(properties, MapEnum.HASH, null, (ForcePair<String, String>) null);
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties, ForcePair<String, String> force) {
        return toOwnMap(properties, MapEnum.HASH, null, force);
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties, MapEnum impl) {
        return toOwnMap(properties, impl, null, (ForcePair<String, String>) null);
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties, MapEnum impl, Comparator<String> c) {
        return toOwnMap(properties, impl, c, (ForcePair<String, String>) null);
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties, MapEnum impl, ForcePair<String, String> force) {
        return toOwnMap(properties, impl, null, force);
    }


    public static OwnMap<String, Object> toOwnMap(Properties properties, MapEnum impl, Comparator<String> c, ForcePair<String, String> force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        if(properties == null || properties.isEmpty()) return new OwnMap<>(impl, c);
        return (OwnMap<String, Object>) private_propertiesAsOwnPairs2(new OwnMap<>(impl, properties.size(), c), properties, force);
    }


    /* ************************************************************************************************************
     *
     *
     *          OwnPair
     *
     * ************************************************************************************************************
     * */

    public static OwnPair toOwnPair(Map source) {
        if(source == null || source.isEmpty()) return new OwnPair();
        return (OwnPair) private_asOwnPairs(new OwnPair(source.size()), source, null);
    }

    public static OwnPair toOwnPair(Map source, ForcePair force) {
        if(source == null || source.isEmpty()) return new OwnPair();
        return (OwnPair) private_asOwnPairs(new OwnPair(source.size()), source, force);
    }

    public static OwnPair toOwnPair(Map source, MapEnum impl) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size()), source, null);
    }

    public static OwnPair toOwnPair(Map source, MapEnum impl, Comparator<String> c) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size(), c), source, null);
    }

    public static OwnPair toOwnPair(Map source, MapEnum impl, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size()), source, force);
    }

    public static OwnPair toOwnPair(Map source, MapEnum impl, Comparator<String> c, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl, c);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size(), c), source, force);
    }


    public static OwnPair toOwnPair(OwnPairs source) {
        if(source == null || source.isEmpty()) return new OwnPair();
        return (OwnPair) private_asOwnPairs(new OwnPair(source.size()), source, null);
    }

    public static OwnPair toOwnPair(OwnPairs source, ForcePair force) {
        if(source == null || source.isEmpty()) return new OwnPair();
        return (OwnPair) private_asOwnPairs(new OwnPair(source.size()), source, force);
    }

    public static OwnPair toOwnPair(OwnPairs source, MapEnum impl) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size()), source, null);
    }

    public static OwnPair toOwnPair(OwnPairs source, MapEnum impl, Comparator<String> c) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl, c);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size(), c), source, null);
    }

    public static OwnPair toOwnPair(OwnPairs source, MapEnum impl, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size()), source, force);
    }

    public static OwnPair toOwnPair(OwnPairs source, MapEnum impl, Comparator<String> c, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(source == null || source.isEmpty()) return new OwnPair(impl, c);
        return (OwnPair) private_asOwnPairs(new OwnPair(impl, source.size(), c), source, force);
    }

    public static OwnPair toOwnPair(Properties properties) {
        if(properties == null || properties.isEmpty()) return new OwnPair();
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(properties.size()), properties, null);
    }

    public static OwnPair toOwnPair(Properties properties, ForcePair force) {
        if(properties == null || properties.isEmpty()) return new OwnPair();
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(properties.size()), properties, force);
    }

    public static OwnPair toOwnPair(Properties properties, MapEnum impl) {
        private_checkMapEnumIsNotNull(impl);
        if(properties == null || properties.isEmpty()) return new OwnPair(impl);
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(impl, properties.size()), properties, null);
    }

    public static OwnPair toOwnPair(Properties properties, MapEnum impl, Comparator<String> c) {
        private_checkMapEnumIsNotNull(impl);
        if(properties == null || properties.isEmpty()) return new OwnPair(impl, c);
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(impl, properties.size(), c), properties, null);
    }

    public static OwnPair toOwnPair(Properties properties, MapEnum impl, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(properties == null || properties.isEmpty()) return new OwnPair(impl);
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(impl, properties.size()), properties, force);
    }

    public static OwnPair toOwnPair(Properties properties, MapEnum impl, Comparator<String> c, ForcePair force) {
        private_checkMapEnumIsNotNull(impl);
        if(properties == null || properties.isEmpty()) return new OwnPair(impl, c);
        return(OwnPair) private_propertiesAsOwnPairs2(new OwnPair(impl, properties.size(), c), properties, force);
    }

    public static <T>OwnPair toOwnPair(Object javaBean) {
        return toOwnPair(javaBean, MapEnum.HASH, null, null);
    }

    public static <T>OwnPair toOwnPair(Object javaBean, ForcePair<String, Object> force) {
        return toOwnPair(javaBean, MapEnum.HASH, null, force);
    }

    public static <T>OwnPair toOwnPair(Object javaBean, MapEnum impl) {
        return toOwnPair(javaBean, impl, null, null);
    }

    public static <T>OwnPair toOwnPair(Object javaBean, MapEnum impl, Comparator<String> c) {
        return toOwnPair(javaBean, impl, c, null);
    }

    public static <T>OwnPair toOwnPair(Object javaBean, MapEnum impl, ForcePair<String, Object> force) {
        return toOwnPair(javaBean, impl, null, force);
    }

    public static <T>OwnPair toOwnPair(Object javaBean, MapEnum impl, Comparator<String> c, ForcePair<String, Object> force) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
        OwnPair result = new OwnPair(impl, c);
        if(javaBean == null) return result;
        addAllFieldValue(result, javaBean, force);
        return result;
    }

    /* ************************************************************************************************************
     *
     *      JsonPair
     *
     * ************************************************************************************************************
     * */

    public static JsonPair toJsonPair(Map map) {
        return new JsonPair().putAll(map);
    }

    public static JsonPair toJsonPair(Map map, ForcePair force) {
        JsonPair jsonPair = new JsonPair();
        if(map == null || map.isEmpty()) return jsonPair;
        if(force == null) {
            return new JsonPair().putAll(map);
        }
        for (Object o : map.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey(), e.getValue());
            if(e == null) continue;
            jsonPair.put(ObjKit.asStringValue(e.getKey(), null), e.getValue());
        }
        return jsonPair;
    }


    public static JsonPair toJsonPair(OwnPairs pairs) {
        return new JsonPair().putAll(pairs);
    }

    public static JsonPair toJsonPair(OwnPairs pairs, ForcePair force) {
        JsonPair jsonPair = new JsonPair();
        if(pairs == null || pairs.isEmpty()) return jsonPair;
        if(force != null) {
            for (Object o : pairs.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                e = force.force(e.getKey(), e.getValue());
                if(e != null) jsonPair.put(ObjKit.asStringValue(e.getKey(), null), e.getValue());
            }
            return jsonPair;
        }
        return new JsonPair().putAll(pairs);
    }


    public static JsonPair toJsonPair(Properties properties) {
        if(properties == null || properties.isEmpty()) return new JsonPair();
        return (JsonPair) private_propertiesAsOwnPairs2(new JsonPair(), properties, null);
    }

    public static JsonPair toJsonPair(Properties properties, ForcePair<String, String> force) {
        if(properties == null || properties.isEmpty()) return new JsonPair();
        return (JsonPair) private_propertiesAsOwnPairs2(new JsonPair(), properties, force);
    }

    public static <T>JsonPair toJsonPair(T javaBean) {
        return toJsonPair(javaBean, null);
    }

    public static <T>JsonPair toJsonPair(T javaBean, ForcePair<String, Object> force) {
        if(javaBean == null) return new JsonPair();
        if(force == null) return new JsonPair().putAll(javaBean);
        Map<String, Object> fieldValueMap = allFieldValue(javaBean);
        JsonPair jsonPair = new JsonPair();
        for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
            e = force.force(e.getKey(), e.getValue());
            if(e != null) jsonPair.put(e.getKey(), e.getValue());
        }
        return jsonPair;
    }

    /* ************************************************************************************************************
     *
     *
     *          Map 等键值对集合转为 Properties
     *
     * ************************************************************************************************************
     * */

    public static Properties toProperties(Map map) {
        return toProperties(map, (ForcePair) null);
    }


    public static Properties toProperties(Map map, ForcePair force) {
        if(map == null || map.isEmpty()) return new Properties();
        Properties properties = new Properties();
        if(force == null) {
            for (Object o : map.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                properties.setProperty(ObjKit.asStringValue(e.getKey(), "null"), ObjKit.toStringEmptyString(e.getValue()));
            }
            return properties;
        }
        for (Object o : map.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey(), e.getValue());
            if(e != null) properties.setProperty(ObjKit.asStringValue(e.getKey(), "null"), ObjKit.toStringEmptyString(e.getValue()));
        }
        return properties;
    }


    public static Properties toProperties(OwnPairs pairs) {
        return toProperties(pairs, (ForcePair) null);
    }

    public static Properties toProperties(OwnPairs pairs, ForcePair force) {
        if(pairs == null || pairs.isEmpty()) return new Properties();
        Properties properties = new Properties();
        if(force != null) {
            for (Object o : pairs.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                e = force.force(e.getKey(), e.getValue());
                if(e == null) continue;
                properties.setProperty(ObjKit.asStringValue(e.getKey(), "null"), ObjKit.toStringEmptyString(e.getValue()));
            }
            return properties;
        }
        for (Object o : pairs.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            properties.setProperty(ObjKit.asStringValue(e.getKey(), "null"), ObjKit.toStringEmptyString(e.getValue()));
        }
        return properties;
    }


    public static Properties toProperties(Object javaBean) {
        return toProperties(javaBean, null);
    }

    public static Properties toProperties(Object javaBean, ForcePair force) {
        if(javaBean == null) return new Properties();
        Map<String, Object> fieldValueMap = allFieldValue(javaBean);
        Properties properties = new Properties();
        if(force == null) {
            for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
                properties.setProperty(e.getKey(), ObjKit.toStringEmptyString(e.getValue()));
            }
            return properties;
        }
        for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
            e = force.force(e.getKey(), e.getValue());
            if(e != null) properties.setProperty(e.getKey(), ObjKit.toStringEmptyString(e.getValue()));
        }
        return properties;
    }


    /* ************************************************************************************************************
     *
     *
     *          拷贝 -> Properties
     *
     * ************************************************************************************************************
     * */


    public static void copy(Map source, Properties target) {
        if(source == null || source.isEmpty() || target == null) return;
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
        }
    }


    public static void copy(Map source, Properties target, ForcePair force) {
        if(source == null || source.isEmpty() || target == null) return;
        if(force == null) {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
            }
            return;
        }
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey(), e.getValue());
            if(e != null) target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
        }
    }



    public static void copy(OwnPairs source, Properties target) {
        if(source != null && !source.isEmpty() && target != null)  {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
            }
        }
    }

    public static void copy(OwnPairs source, Properties target, ForcePair force) {
        if(source == null || source.isEmpty() || target == null) return;
        if(force != null) {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                e = force.force(e.getKey(), e.getValue());
                if(e == null) continue;
                target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
            }
            return;
        }
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            target.setProperty(ObjKit.toStringNullString(e.getKey()), ObjKit.toStringEmptyString(e.getValue()));
        }
    }



    public static void copy(Properties source, Properties target) {
        if(source == null || source.isEmpty() || target == null) return;
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            target.setProperty(e.getKey().toString(), e.getValue().toString());
        }
    }

    public static void copy(Properties source, Properties target, ForcePair<String, String> force) {
        if(source == null || source.isEmpty() || target == null) return;
        if(force == null) {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                target.setProperty(e.getKey().toString(), e.getValue().toString());
            }
            return;
        }
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey().toString(), e.getValue().toString());
            if(e == null) continue;
            target.setProperty(ObjKit.asStringValue(e.getKey(), "null"), ObjKit.asStringValue(e.getValue(), "null"));
        }
    }


    public static <T>void copy(T sourceJavaBean, Properties target) {
        copy(sourceJavaBean, target, null);
    }

    public static <T>void copy(T sourceJavaBean, Properties target, ForcePair<String, Object> force) {
        if(sourceJavaBean == null || target == null) return;
        Map<String, Object> fieldValueMap = allFieldValue(sourceJavaBean);
        if(force == null) {
            for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
                target.setProperty(ObjKit.asStringValue(e.getKey(), null), ObjKit.toStringEmptyString(e.getValue()));
            }
            return;
        }
        for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
            e = force.force(e.getKey(), e.getValue());
            if(e != null) target.setProperty(ObjKit.asStringValue(e.getKey(), null), ObjKit.toStringEmptyString(e.getValue()));
        }
    }

    /* ************************************************************************************************************
     *
     *          拷贝 -> OwnPairs
     *
     * ************************************************************************************************************
     * */

    public static <K, V>void copy(Map source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType) {
        copy(source, target, keyType, valueType, (ForcePair<K, V>) null);
    }

    public static <K, V>void copy(Map source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType, ForcePair<K, V> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_toOwnPairs(target, source, keyType, valueType, force);
    }

    public static <K, V>void copy(Map<? extends K, ? extends V> source, OwnPairs<K, V> target) {
        copy(source, target, null);
    }

    public static <K, V>void copy(Map<? extends K, ? extends V> source, OwnPairs<K, V> target, ForcePair<K, V> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_asOwnPairs(target, source, force);
    }

    public static <K, V>void copy(OwnPairs source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType) {
        copy(source, target, keyType, valueType, (ForcePair<K, V>) null);
    }

    public static <K, V>void copy(OwnPairs source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType, ForcePair<K, V> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_toOwnPairs(target, source, keyType, valueType, force);
    }

    public static <K, V>void copy(OwnPairs<? extends K, ? extends V> source, OwnPairs<K, V> target) {
        copy(source, target, null);
    }

    public static <K, V>void copy(OwnPairs<? extends K, ? extends V> source, OwnPairs<K, V> target, ForcePair<K, V> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_asOwnPairs(target, source, force);
    }

    public static <K, V>void copy(Properties source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType) {
        copy(source, target, keyType, valueType, (ForcePair<K, V>) null);
    }

    public static <K, V>void copy(Properties source, OwnPairs<K, V> target, C<K> keyType, C<V> valueType, ForcePair<K, V> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_toOwnPairs(target, source, keyType, valueType, force);
    }

    public static <K, V, T>void copy(T sourceJavaBean, OwnPairs<K, V> target, C<K> keyType, C<V> valueType) {
        copy(sourceJavaBean, target, keyType, valueType, null);
    }

    public static <K, V, T>void copy(T sourceJavaBean, OwnPairs<K, V> target, C<K> keyType, C<V> valueType, ForcePair<String, Object> force) {
        if(sourceJavaBean == null || target == null) return;
        Map<String, Object> fieldValueMap = allFieldValue(sourceJavaBean);
        if(force != null) {
            for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
                e = force.force(e.getKey(), e.getValue());
                if(e == null) continue;
                target.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
            }
            return;
        }
        for (Map.Entry<String, Object> e : fieldValueMap.entrySet()) {
            target.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
        }
    }


    public static void propertiesCopy(Properties source, OwnPairs<String, String> target) {
        propertiesCopy(source, target, null);
    }

    public static void propertiesCopy(Properties source, OwnPairs<String, String> target, ForcePair<String, String> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_propertiesAsOwnPairs(target, source, force);
    }

    public static void copy(Properties source, OwnPairs<String, Object> target) {
        copy(source, target, null);
    }

    public static void copy(Properties source, OwnPairs<String, Object> target, ForcePair<String, String> force) {
        if(source == null || source.isEmpty() || target == null) return;
        private_propertiesAsOwnPairs2(target, source, force);
    }

    /* ************************************************************************************************************
     *
     *
     *          私有逻辑
     *
     * ************************************************************************************************************
     * */

    @Note("检查 MapEnum 枚举实例不能为 null")
    private static void private_checkMapEnumIsNotNull(MapEnum impl) {
        if(impl == null) throw new NullPointerException("实现自定义键值对容器集合的 MapEnum 参数为 null");
    }

    @Note("将 source 里的内容拷贝到 result 里，拷贝过程中会根据 forcePair 来判断是否要对 Map.Entry 做一些自定义增强操作")
    private static <K, V>OwnPairs<K, V> private_toOwnPairs(OwnPairs<K, V> result, Map source, C<K> keyType, C<V> valueType, ForcePair force) {
        if(force == null) {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                result.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
            }
            return result;
        }
        for (Object o : source.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey(), e.getValue());
            if(e == null) continue;
            result.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
        }
        return result;
    }

    @Note("将 source 里的内容拷贝到 result 里，拷贝过程中会根据 forcePair 来判断是否要对 Map.Entry 做一些自定义增强操作")
    private static <K, V>OwnPairs<K, V> private_toOwnPairs(OwnPairs<K, V> result, OwnPairs source, C<K> keyType, C<V> valueType, ForcePair force) {
        if(force == null) {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                result.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
            }
        }
        else {
            for (Object o : source.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                e = force.force(e.getKey(), e.getValue());
                if(e != null) result.put((K) ObjKit.toRealValue(e.getKey(), keyType), (V) ObjKit.toRealValue(e.getValue(), valueType));
            }
        }
        return result;
    }


    @Note("将 source 的内容拷贝到 result，拷贝过程中会对 Map.Entry 做一些自定义增强逻辑")
    private static <K, V> OwnPairs<K, V> private_asOwnPairs(OwnPairs<K, V> result, Map<? extends K, ? extends V> source, ForcePair<K, V> force) {
        if(force == null) {
            result.putAll(source);
            return result;
        }
        Set<? extends Map.Entry<? extends K, ? extends V>> entries = source.entrySet();
        for (Map.Entry<? extends K, ? extends V> e : entries) {
            Map.Entry<K, V> fe = force.force(e.getKey(), e.getValue());
            if(fe != null) result.put(fe.getKey(), fe.getValue());
        }
        return result;
    }


    @Note("将 source 的内容拷贝到 result，拷贝过程中会对 Map.Entry 做一些自定义增强逻辑")
    private static <K, V> OwnPairs<K, V> private_asOwnPairs(OwnPairs<K, V> result, OwnPairs<? extends K, ? extends V> source, ForcePair<K, V> force) {
        if(force == null) {
            result.putAll(source);
        }
        else {
            Set<? extends Map.Entry<? extends K, ? extends V>> entries = source.entrySet();
            for (Map.Entry<? extends K, ? extends V> e : entries) {
                Map.Entry<K, V> fe = force.force(e.getKey(), e.getValue());
                if(fe == null) continue;
                result.put(fe.getKey(), fe.getValue());
            }
        }
        return result;
    }

    @Note("将 source 里的数据拷贝到 result 里，拷贝过程中会将 key、value 转为字符串和 Object")
    private static OwnPairs<String, String> private_propertiesAsOwnPairs(OwnPairs<String, String> result, Properties properties, ForcePair<String, String> force) {
        if(force == null) {
            for (Object o : properties.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                result.put(e.getKey().toString(), e.getValue().toString());
            }
            return result;
        }
        for (Object o : properties.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            e = force.force(e.getKey().toString(), e.getValue().toString());
            if(e != null) result.put(e.getKey().toString(), e.getValue().toString());
        }
        return result;
    }

    @Note("将 source 里的数据拷贝到 result 里，拷贝过程中会将 key、value 转为字符串和 Object" +
            "注意，Properties 如果有 JSON 字符串不会自动反序列化为对象。因为 JSON ")
    private static OwnPairs<String, Object> private_propertiesAsOwnPairs2(OwnPairs<String, Object> result, Properties properties, ForcePair<String, String> force) {
        if(force != null) {
            for (Object o : properties.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                e = force.force(e.getKey().toString(), e.getValue().toString());
                if(e != null) result.put(ObjKit.asStringValue(e.getKey(), null), ObjKit.stringToRealValue(ObjKit.asStringValue(e.getValue(), null), true));
            }
            return result;
        }
        for (Object o : properties.entrySet()) {
            Map.Entry e = (Map.Entry) o;
            result.put(e.getKey().toString(), ObjKit.stringToRealValue(e.getValue().toString(), true));
        }
        return result;
    }

}
